package com.hui.platform.falseworkapi.service.business.user.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hui.platform.falseworkapi.common.core.vo.PageData;
import com.hui.platform.falseworkapi.common.security.constant.JwtProperties;
import com.hui.platform.falseworkapi.common.security.constant.SecurityConstant;
import com.hui.platform.falseworkapi.common.security.utils.JwtTokenUtil;
import com.hui.platform.falseworkapi.common.security.utils.SecurityUtils;
import com.hui.platform.falseworkapi.service.business.user.bo.TbUserBO;
import com.hui.platform.falseworkapi.service.business.user.constant.UserBusinessErrorEnum;
import com.hui.platform.falseworkapi.service.business.user.convert.TbUserConvert;
import com.hui.platform.falseworkapi.service.business.user.dto.TbUserDTO;
import com.hui.platform.falseworkapi.service.business.user.dto.TbUserLoginDTO;
import com.hui.platform.falseworkapi.service.business.user.dto.TbUserSaveDTO;
import com.hui.platform.falseworkapi.service.business.user.entity.TbAuthorities;
import com.hui.platform.falseworkapi.service.business.user.entity.TbUser;
import com.hui.platform.falseworkapi.service.business.user.event.RegisterUserEvent;
import com.hui.platform.falseworkapi.service.business.user.mapper.TbUserMapper;
import com.hui.platform.falseworkapi.service.business.user.service.TbAuthoritiesService;
import com.hui.platform.falseworkapi.service.business.user.service.TbUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 用户表 服务实现类
 *
 * @author hui
 * @since 2020-04-14
 */
@Service
public class TbUserServiceImpl extends ServiceImpl<TbUserMapper, TbUser> implements TbUserService {

    private static final Logger LOGGER = LoggerFactory.getLogger(TbUserServiceImpl.class);

    @Autowired
    @Lazy
    private UserDetailsService userDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private TbAuthoritiesService tbAuthoritiesService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private JwtProperties jwtProperties;

    //发布事件
    private final ApplicationContext applicationContext;

    public TbUserServiceImpl(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public TbUserBO readById(Long id) {
        return TbUserConvert.INSTANCE.do2bo(getById(id));
    }

    @Override
    public List<TbUserBO> readByIds(List<Long> ids) {
        return TbUserConvert.INSTANCE.do2bo(new ArrayList<>(listByIds(ids)));
    }

    @Override
    public List<TbUserBO> readList(TbUserDTO condition) {
        return TbUserConvert.INSTANCE.do2bo(list(Wrappers.lambdaQuery(TbUserConvert.INSTANCE.dto2do(condition))));
    }

    @Override
    public PageData<TbUserBO> readPage(Long pageNum, Long pageSize, TbUserDTO condition) {
        IPage<TbUser> page = page(new Page<>(pageNum, pageSize), Wrappers.lambdaQuery(TbUserConvert.INSTANCE.dto2do(condition)));
        return PageData.build(page, TbUserConvert.INSTANCE.do2bo(page.getRecords()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createOne(TbUserSaveDTO dto) {
        TbUser domain = TbUserConvert.INSTANCE.dto2do(dto);
        domain.setPassword(passwordEncoder.encode(domain.getPassword()))
                .setCreated(new Date());
        TbAuthorities tbAuthorities = new TbAuthorities();
        save(domain);
        tbAuthorities.setAuthroity(SecurityConstant.SYSTEM_USER)
                .setUserId(domain.getId());
        tbAuthoritiesService.save(tbAuthorities);
        //发布监听事件
        applicationContext.publishEvent(new RegisterUserEvent(this, domain));
        return domain.getId();
    }

    @Override
    public Long updateOne(Long id, TbUserSaveDTO dto) {
        return updateById(TbUserConvert.INSTANCE.dto2do(dto).setId(id)) ? id : null;
    }

    @Override
    public Long deleteById(Long id) {
        return removeById(id) ? id : null;
    }

    @Override
    public List<Long> deleteByIds(List<Long> ids) {
        return removeByIds(ids) ? ids : null;
    }

    @Override
    public String userLogin(TbUserLoginDTO dto) {
        String token = null;
        try {
            UserDetails userDetails = SecurityUtils.authenticate(dto.getUsername(),
                    dto.getPassword(),
                    userDetailsService,
                    passwordEncoder);
            token = jwtProperties.getTokenStartHead() + jwtTokenUtil.generateToken(userDetails);
        }catch (Exception e){
            UserBusinessErrorEnum.LOGIN_FAIL.throwException();
            LOGGER.warn("登录异常:{}", e.getMessage());
        }
        return token;
    }

}
